package classfile

import (
	"fmt"
)

type AttributeInfo interface {
	readAttr(cp ConstantPool) AttributeInfo
}

type AttributeData struct {
	ClassReader
}

type AttrStruct struct {
	nameIndex     uint16
	length        uint32
	attributeName *Constant_Utf8
	attributeData AttributeData
}

func (self *AttrStruct) readAttr(cp ConstantPool) AttributeInfo {
	var attrName = self.attributeName.Value
	switch attrName {
	case "Code":
		return (&CodeAttr{AttrStruct: *self}).readAttr(cp)
	case "ConstantValue":
		return (&ConstantValueAttr{AttrStruct: *self}).readAttr(cp)
	case "LineNumberTable":
		return (&LineNumberTableAttr{AttrStruct: *self}).readAttr(cp)
	case "LocalVariableTable":
		return (&LocalVariableTableAttr{AttrStruct: *self}).readAttr(cp)
	case "StackMapTable":
		//?
		return (&StackMapTableAttr{AttrStruct: *self}).readAttr(cp)
	case "Exceptions":
		return (&ExceptionTableAttr{AttrStruct: *self}).readAttr(cp)
	case "LocalVariableTypeTable":
		return (&LocalVariableTypeTableAttr{AttrStruct: *self}).readAttr(cp)
	case "Signature":
		return (&SignatureAttr{AttrStruct: *self}).readAttr(cp)
	case "SourceFile":
		return (&SourceFileAttr{AttrStruct: *self}).readAttrInfo(cp)
	case "RuntimeVisibleAnnotations":
		//?
		return (&RuntimeVisibleAnnotationsAttr{AttrStruct: *self}).readAttrInfo(cp)
	case "InnerClasses":
		//?
		return (&InnerClassesAttr{AttrStruct: *self}).readAttrInfo(cp)
	case "BootstrapMethods":
		//?
		return (&BootstrapMethodsAttr{AttrStruct: *self}).readAttr(cp)
	default:
		fmt.Println("属性不支持1:" + attrName)
		return self
	}
}

func NewAttributeInfo(cr *ClassReader, cp ConstantPool) AttributeInfo {
	attr := &AttrStruct{}
	attr.nameIndex = cr.ReadUInt16()
	attr.length = cr.ReadUInt32()
	attr.attributeName = cp.GetConstant(attr.nameIndex).(*Constant_Utf8)
	attr.attributeData = AttributeData{
		(&ClassReader{}).SetData(cr.ReadBytes(attr.length)),
	}
	return attr.readAttr(cp)
}
